namespace LangChain.Base.Tracers;

/// <summary>
/// Base Run schema.
/// Contains the fundamental fields to define a run in a system.
/// </summary>
public abstract class RunBase
{
    /// <summary>
    /// Unique identifier for the run.
    /// </summary>
    public string Id { get; set; } = string.Empty;

    /// <summary>
    /// Human-readable name for the run.
    /// </summary>
    public string Name { get; set; } = string.Empty;

    /// <summary>
    /// Start time of the run.
    /// </summary>
    public DateTime StartTime { get; set; }

    /// <summary>
    /// The type of run, such as tool, chain, llm, retriever,
    /// embedding, prompt, parser.
    /// </summary>
    public string RunType { get; set; } = string.Empty;

    /// <summary>
    /// End time of the run, if applicable.
    /// </summary>
    public DateTime? EndTime { get; set; }

    /// <summary>
    /// Additional metadata or settings related to the run.
    /// </summary>
    public Dictionary<string, object> ExtraData { get; set; } = new();

    /// <summary>
    /// Error message, if the run encountered any issues.
    /// </summary>
    public string Error { get; set; } = string.Empty;

    /// <summary>
    /// Serialized object that executed the run for potential reuse.
    /// </summary>
    public Dictionary<string, object> Serialized { get; set; } = new();

    /// <summary>
    /// List of events associated with the run, like start and end events.
    /// </summary>
    public List<Dictionary<string, object>> Events { get; set; } = new();

    /// <summary>
    /// Inputs used for the run.
    /// </summary>
    public Dictionary<string, object> Inputs { get; set; } = new();

    /// <summary>
    /// Outputs generated by the run, if any.
    /// </summary>
    public Dictionary<string, object> Outputs { get; set; } = new();

    /// <summary>
    /// Reference to an example that this run may be based on.
    /// </summary>
    public Guid? ReferenceExampleId { get; set; }

    /// <summary>
    /// Identifier for a parent run, if this run is a sub-run.
    /// </summary>
    public string? ParentRunId { get; set; }

    /// <summary>
    /// Tags for categorizing or annotating the run.
    /// </summary>
    public List<string> Tags { get; set; } = new();
}

/// <summary>
/// Run schema in the Tracer
/// </summary>
public class Run : RunBase
{
    /// <summary>
    /// The execution order of the run within a run trace.
    /// </summary>
    public int ExecutionOrder { get; set; }

    /// <summary>
    /// 
    /// </summary>
    public int? ChildExecutionOrder { get; set; }

    /// <summary>
    /// The child runs of this run
    /// </summary>
    public List<Run> ChildRuns { get; set; } = new();

    // TODO: name init;
    // @root_validator(pre=True)
    // def assign_name(cls, values: dict) -> dict:
    //     """Assign name to the run."""
    //     if values.get("name") is None:
    //         if "name" in values["serialized"]:
    //             values["name"] = values["serialized"]["name"]
    //         elif "id" in values["serialized"]:
    //             values["name"] = values["serialized"]["id"][-1]
    //     if values.get("events") is None:
    //         values["events"] = []
    //     return values
}

/// <summary>
/// 
/// </summary>
public static class RunExtensions
{

}
